package com.codefactory.generator.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.codefactory.generator.method.ClassNameMethod;
import com.codefactory.generator.method.UpperCaseMethod;
import com.codefactory.generator.method.VarNameMethod;
import com.codefactory.generator.model.FTLDataModel;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;

public class FreemarkerUtil {

    private static final Configuration CFG = new Configuration(Configuration.VERSION_2_3_31);

    static {
        CFG.setDefaultEncoding("UTF-8");
        CFG.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        CFG.setSharedVariable("upper", new UpperCaseMethod());
        CFG.setSharedVariable("varName", new VarNameMethod());
        CFG.setSharedVariable("className", new ClassNameMethod());
        //${upper("hello world")}  // 返回 "HELLO WORLD"
    }

    public static Configuration getConfiguration(File templateLoadDir) throws IOException {
        Configuration cfg = new Configuration(freemarker.template.Configuration.VERSION_2_3_23);
        cfg.setDirectoryForTemplateLoading(templateLoadDir);
        cfg.setDefaultEncoding("UTF-8");
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        cfg.setSharedVariable("upper", new UpperCaseMethod());
        cfg.setSharedVariable("varName", new VarNameMethod());
        cfg.setSharedVariable("className", new ClassNameMethod());
        //${upper("hello world")}  // 返回 "HELLO WORLD"
        return cfg;
    }

    public static JSONObject ftlDataModelToJSONObject(FTLDataModel ftlDataModel) {
        JSONObject dataModel = JSON.parseObject(JSON.toJSONString(ftlDataModel));
        return dataModel;
    }

    /**
     * 直接使用字符串作为模板 输出字符串内容
     *
     * @param templateName   模板名称
     * @param templateString 字符串作为模板
     * @param dataModel
     * @return
     * @throws Exception
     */
    public static String processToString(String templateName, String templateString, Object dataModel) throws Exception {
        // 创建模板对象
        Template template = new Template(StringUtils.defaultString(templateName, "template"), templateString, CFG);

        String result;
        StringWriter out = new StringWriter();
        try {
            template.process(dataModel, out);
            out.flush();
            result = out.toString();
        } finally {
            out.close();
        }
        return result;
    }

    /**
     * 直接使用字符串作为模板 输出文件内容
     *
     * @param templateName   模板名称
     * @param templateString 字符串作为模板
     * @param outputFile     输出文件
     * @param dataModel
     * @throws Exception
     */
    public static void processToFile(String templateName, String templateString, File outputFile, Object dataModel) throws Exception {
        // 创建模板对象
        Template template = new Template(StringUtils.defaultString(templateName, "template"), templateString, CFG);

        // 创建输出文件的父目录（如果不存在）
        File outputDir = outputFile.getParentFile();
        if (!outputDir.exists()) {
            outputDir.mkdirs();
        }

        // 生成代码并保存到文件
        try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), StandardCharsets.UTF_8))) {
            template.process(dataModel, out);
            out.flush();
        }
    }
}
